<?php
namespace App\Services;
use App\Helpers\Api\PayTrait;
use App\Helpers\Api\TtMiniTrait;
use App\Models\Appoint;
use App\Models\HoneyBalance;
use App\Models\Material;
use App\Models\MaterialSnapshot;
use App\Models\Order;
use App\Models\User;

class OrderService {
    use PayTrait, TtMiniTrait;

    public static function is_buy($user_id, $entity_id, $type) {
        return Order::where('user_id', $user_id)
            ->where('entity_type', $type)
            ->where('entity_id', $entity_id)
            ->where('status', Order::PAID_SUCCESS)->exists();
    }

    public static function create_pay($user_id, $entity_id, $entity_type, $pay_platform) {
        $self = new self();
        $user = User::find($user_id);

        $entity = null;
        $pay_type = Order::PAY_TYPE_WX;
        if ($entity_type == Order::ENTITY_MATERIAL) {
            if (OrderService::is_buy($user_id, $entity_id, Order::ENTITY_MATERIAL)) {
                throw new \Exception('已购买素材，请勿重复购买');
            }
            $prefix = 'mt';
            $model = new Material();
            $entity = $model->find($entity_id);
//            if ($entity->user_id == $user_id) {
//                throw new \Exception('自己发布素材，无需购买');
//            }
            $amount = $entity->amount;
            $subject = $entity->title;
            $pay_type = $entity->buy_type;
            $category_id = $entity->category_id;
        } else{
            $prefix = 'ap';
            $model = new Appoint();
            $entity = $model->withCertain('service', ['title'])->find($entity_id);
            if ($entity->status != 1)
                throw new \Exception('当前状态无法支付');

            $amount = $entity->amount;
            $subject = $entity->service->title ?? '拍片儿';
            $category_id = $entity->category;
        }
        $out_trade_no = create_order_no($prefix);

        $create_pay = true;
        try {
            \DB::beginTransaction();
            $data = [
                'user_id' => $user_id,
                'entity_user_id' => $entity->user_id,
                'entity_type' => $entity_type,
                'entity_id' => $entity->id,
                'category_id' => $category_id,
                'order_sn' => $out_trade_no,
                'origin_amount' => $amount,
                'paid_amount' => $amount,
                'pay_type' => Order::PAY_TYPE_WX,
            ];
            if ($entity_type == Order::ENTITY_MATERIAL) {
                //生成快照表
                $arr = $entity->toArray();
                unset($arr['id'], $arr['amount_yuan']);
                $snapshot = new MaterialSnapshot();
                foreach ($arr as $key => $value) {
                    $snapshot-> {$key} = $value;
                }
                $snapshot->save();
                $data['material_snopshot_id'] = $snapshot->id;

                //素材首次购买免费
                $exists = Order::where('user_id', $user_id)->where('entity_type', Order::ENTITY_MATERIAL)->exists();
                if (!$exists) {
                    $data['status'] = Order::PAID_SUCCESS;
                    $data['paid_amount'] = 0;
                    $create_pay = false;
                }
            }

            if ($pay_type == Material::BUY_TYPE_HONEY) {
                $data['status'] = Order::PAID_SUCCESS;
                $data['pay_type'] = Order::PAY_TYPE_HONEY;
                $amount_yuan = format_yuan($amount);
                //判断用户蜜糖是否足够
                if ($user->honey_balance < $amount_yuan)
                    throw new \Exception('蜜糖余额不足');

                HoneyBalanceService::store($user_id, -$amount_yuan, HoneyBalance::TYPE_CONSUME, $entity_id, false);
                HoneyBalanceService::store($entity->user_id, $amount_yuan, HoneyBalance::TYPE_EARN, $entity_id, false);
                $result = ['url' => $entity->url];
            } else if($create_pay) {
                if ($pay_platform == 'miniapp') {
                    $config = [
                        'out_trade_no' => $out_trade_no,
                        'total_fee' => $amount,
                        'body' => $subject,
                        'openid' => $user->openid,
                        'trade_type' => 'JSAPI'
                    ];
                    $result = $self->payWx()->{$pay_platform}($config);
                } else {
                    $config = [
                        'out_trade_no' => $out_trade_no,
                        'total_fee' => $amount,
                        'body' => $subject,
                    ];
                    $response = $self->payWx()->{$pay_platform}($config);
                    $result['code_url'] = $response->code_url;
                    $result['out_trade_no'] = $out_trade_no;
                    $result['total_fee'] = $entity->amount_yuan;
                }
            } else {
                $result = null;
            }
            $model = Order::create($data);
            \DB::commit();
            return ['pay_type' => $pay_type, 'result' => $result, 'order_id' => $model->id];
        }catch (\Exception $e) {
            \DB::rollBack();
            throw new \Exception($e->getMessage());
        }
    }

    public static function pay_result($out_trade_no, $total_amount, $trade_no) {
        try {
            \DB::transaction(function () use($out_trade_no, $total_amount, $trade_no){
                $order = Order::where('order_sn', $out_trade_no)->first();
                \Log::info(date('Y-m-d H:i:s'));
                if (!$order) {
                    throw new \Exception('订单号不存在');
                }
                //防止
                $order = Order::lockForUpdate()->find($order->id);
                if ($order->status == Order::PAID_SUCCESS) {
                    return;
                }
                if ($order->paid_amount != $total_amount) {
                    throw new \Exception('订单金额不正确');
                }
                $order->out_trade_no = $trade_no;
                $order->status = Order::PAID_SUCCESS;
                $order->save();
                if ($order->entity_type == Order::ENTITY_APPOINT) {
                    $appoint = Appoint::find($order->entity_id);
                    $appoint->status = Appoint::STATUS_PAID;
                    $appoint->pay_type = Appoint::PAY_TYPE_WX;
                    $appoint->save();
                    HoneyBalanceService::store($order->user_id, HoneyBalance::POINT_APPOINT_PAY, HoneyBalance::TYPE_APPOINT, $appoint->id, true);
                } else {
                    $material = Material::find($order->entity_id);
                    $material->buy_num = $material->buy_num + 1;
                    $material->save();
                    BalanceService::store($order->entity_user_id, $total_amount, $order->entity_type, $order->id, false);
                }
            });
        }catch (\Exception $e) {
            throw new \Exception($e->getMessage());
        }
    }

    public static function getMaterialCashAmount() {
        $paid_amount = Order::where('entity_type', Order::ENTITY_MATERIAL)->whereIn('pay_type', [Order::PAY_TYPE_WX])->sum('paid_amount');
        return format_yuan($paid_amount);
    }

    public static function getMaterialHoneyAmount() {
        $paid_amount = Order::where('entity_type', Order::ENTITY_MATERIAL)->whereIn('pay_type', [Order::PAY_TYPE_HONEY])->sum('paid_amount');
        return format_yuan($paid_amount);
    }


}
